import PSO from "../common/calc/pso";
import Vector from "../common/calc/vector";
import {Target, FakeTarget} from "./target";
import Interferencer from "./interfer";
import deploy_const from "./constant";
import Array from "../common/utils/array_ext"
import Monitor from "./monitor";
import {Aerocraft} from "../common/module/aerocraft"

// 群体类
function Flock(canvas, iteration_sum = 1000) {
    // 获得绘图对象
    this.canvas = canvas;
    // 获得监控器对象
    this.monitor = new Monitor();
    // 群体最大迭代次数
    this.iteration_sum = iteration_sum;
    // 群体当前迭代次数
    this.iteration = 0;
    // 网格的默认值
    this.grid = null;
    // 干扰物列表
    this.inter_list = [];
    // 目标列表
    this.target_list = [];
    // 无人机列表
    this.uav_list = [];
    // 评估值变化情况
    this.evaluation = [];
    // 采用的算法
    this.algorithm = null;

    // 增加网格
    this.addGrid = function (grid) {
        this.grid = grid;
    };

    // 删除网格
    this.delGrid = function () {
        if (this.grid != null) {
            // 清空目标分布的文本框
            $("#randomValue").val("");
            // 令轨迹对象为空
            this.grid = null;
        }
    };

    this.add_uav = function (uav) {
        this.uav_list.push(uav);
    };

    // 增加目标
    this.addTarget = function (target) {
        this.target_list.push(target)
    };

    // 从储存中增加目标
    this.add_targets_from_store = function () {
        console.log("增加情况");
        // 取得textarea中真目标的分布位置值
        let true_textarea_val = document.getElementById("true_target_locations").value.trim();
        // 取得localstory中的值
        let true_local_val = localStorage.getItem(deploy_const.get("真目标分布位置"));
        // 设定顺序为:1. textarea中的值, 2.localstorage, 3.随机生成
        if (true_textarea_val.length > 10) {
            this.string_to_targets(true_textarea_val);
            localStorage.setItem(deploy_const.get("真目标分布位置"), true_textarea_val);
        } else if (true_local_val != null && true_local_val.length > 10) {
            this.string_to_targets(true_local_val);
            document.getElementById("true_target_locations").value = true_local_val;
        } else {
            this.add_all_targets();
        }

        // 取得textarea中假目标的分布位置值
        let fake_textarea_val = document.getElementById("fake_target_locations").value.trim();
        // 取得localstory中的值
        let fake_local_val = localStorage.getItem(deploy_const.get("假目标分布位置"));
        // 设定顺序为:1. textarea中的值, 2.localstorage, 3.随机生成
        if (fake_textarea_val.length > 10) {
            this.string_to_targets(fake_textarea_val, "switch");
            localStorage.setItem(deploy_const.get("假目标分布位置"), fake_textarea_val);
        } else if (fake_local_val != null && fake_local_val.length > 10) {
            this.string_to_targets(fake_local_val, "switch");
            document.getElementById("fake_target_locations").value = fake_local_val;
        } else {
            this.add_all_targets();
        }


    };

    /**
     * 根据给定的目标数,一次性随机生成指定个数的真,假目标
     */
    this.add_all_targets = function () {
        this.removeTargetAll();
        // 增加指定的真目标数量
        let true_target_num = $("#true_target_num").val() - 0;
        for (let i = 0; i < true_target_num; i++) {
            let rand_x = Math.random() * this.canvas.width;
            let rand_y = Math.random() * this.canvas.height;
            this.addTarget(new Target(rand_x, rand_y))
        }
        // 增加指定的假目标数目
        let fake_target_num = $("#fake_target_num").val() - 0;
        for (let i = 0; i < fake_target_num; i++) {
            let rand_x = Math.random() * this.canvas.width;
            let rand_y = Math.random() * this.canvas.height;
            this.addTarget(new FakeTarget(rand_x, rand_y))
        }

        // 将目标坐标写入textarea
        let true_pos_str = "";
        let fake_pos_str = "";
        for (let target of this.target_list) {
            if (target instanceof FakeTarget) {
                fake_pos_str += target.toString();
            } else {
                true_pos_str += target.toString();
            }
        }
        document.getElementById("true_target_locations").value = true_pos_str;
        document.getElementById("fake_target_locations").value = fake_pos_str;
        localStorage.setItem(deploy_const.get("真目标分布位置"), true_pos_str);
        localStorage.setItem(deploy_const.get("假目标分布位置"), fake_pos_str);
    };

    /**
     * 将字符串转换成目标分布
     * @param info 字符串
     */
    this.string_to_targets = function (info, type = "true") {
        // // 首先移除所有目标
        // this.removeTargetAll();
        // 将信息进行拆分
        let info_list = info.split("&#");
        let target_num = Math.floor(info_list.length / 2);
        for (let i = 0; i < target_num; i++) {
            let [x, y] = [info_list[i * 2], info_list[i * 2 + 1]];
            if (type === "true") {
                this.addTarget(new Target(x, y))
            } else {
                this.addTarget(new FakeTarget(x, y))
            }
        }
    };

    //删除目标
    this.delTarget = function () {
        this.target_list.pop()
    };

    // 删除所有目标
    this.removeTargetAll = function () {
        this.target_list = [];
    };

    this.addInterfer = function (interfer) {
        this.inter_list.push(interfer);
    };

    this.delInterfer = function () {
        this.inter_list.pop();
    };

    this.removeInterfer = function () {
        while (this.inter_list.length > 0) {
            this.inter_list.pop()
        }
    };

    /**
     * 探测函数
     * @param dis  目标到干扰物的距离
     * @param range  干扰半径
     * @returns {number}  被探测到的系数
     */
    this.discover_func = function (dis_list, range) {
        // 筛选出距离中小于干扰范围的值
        dis_list = dis_list.filter(x => x < range);
        // 如果筛选出的干扰物没有,则返回1
        if (dis_list.length == 0) {
            return 1;
        } else if (dis_list.length == 1) {
            let dis = dis_list[0];
            return (dis * dis) / (range * range)
        } else if (dis_list.length > 1) {
            let discover_index = 1;
            for (let dis of dis_list) {
                discover_index = discover_index * ((dis * dis) / (range * range));
            }
            return discover_index
        }
    };

    // 干扰物的评估函数,即被发现的概率
    this.evaluate = function (solution) {
        // 所有目标的被发现系数
        let discover_index = 0;
        let len = solution.length;
        // 干扰器个数
        let inter_num = Math.floor(len / 2);
        // 干扰器范围
        let inter_range = document.getElementById("inter_range").value - 0;
        // 所有干扰器的列表
        let inter_list = [];
        for (let i = 0; i < inter_num; i++) {
            let inter = new Vector(solution[2 * i], solution[2 * i + 1]);
            inter_list.push(inter);
        }
        for (let target of this.target_list) {
            // 获得目标到干扰物的最近距离
            let target_pos = target.pos;
            // 获得每个干扰物到目标的距离
            let dis_list = inter_list.map(x => x.euc2d(target_pos));
            // 将单个目标被发现的系数累加到总系数中
            discover_index += this.discover_func(dis_list, inter_range);
        }
        return discover_index
    };

    // 设置算法情况
    this.set_algorithm = function () {
        // 干扰物数量
        let inter_num = document.getElementById("inter_num").value - 0;
        if (inter_num > 0) {
            let dimension = inter_num * 2;
            let ub = [this.canvas.width, this.canvas.height].repeat(inter_num);
            let lb = [0, 0].repeat(inter_num);
            this.algorithm = new PSO(dimension, ub, lb, this.evaluate, 20, 1000, this);
        }
    };

    this.fly = function () {
        for (let uav of this.uav_list) {
            if (!uav.hasFlyTarget()) {
                this.set_near_target(uav)
            }
            if (uav.near) {
                uav.current_target.is_dead = true;
                // let target_num = Math.floor(Math.random() * this.target_list.length);
                // for (let target of this.target_list) target.is_find = false;
                // this.target_list[target_num].is_find = true;
                // uav.set_target(this.target_list[target_num].pos.x, this.target_list[target_num].pos.y);
                this.set_near_target(uav);
            }
            uav.fly();
        }
    };

    /**
     * 将无人机的目标设置为最近的那个
     * @param uav
     */
    this.set_near_target = function(uav){
        let near_target = null;
        let near_dis = Infinity;
        for (let target of this.target_list) {
            if (target.is_work) {
                if(target.is_dead === true) continue;
                let dis = uav.pos.euc2d(target.pos);
                if (dis < near_dis) {
                    near_target = target;
                    near_dis = dis;
                }
            }
        }
        // 如果near_target存在,则进行设置
        if(near_target){
            // 如果无人机之前有目标,则转换之后要将那个目标的激活状况取消掉
            if(uav.current_target) uav.current_target.is_active = false;
            near_target.active();
            uav.setTarget(near_target);
            uav.setFlyPos(near_target.pos.x, near_target.pos.y);
        }
    };

    // 更新数据方法
    this.update = function () {
        this.fly();
    };

    /**
     * 根据解的情况绘制干扰物
     * @param solution
     */
    this.set_refer = function (solution) {
        // 清空干扰物
        this.removeInterfer();
        let inter_range = document.getElementById("inter_range").value - 0;
        let len = solution.length;
        // 干扰器个数
        let inter_num = Math.floor(len / 2);
        // 所有干扰器的列表
        let inter_list = [];
        for (let i = 0; i < inter_num; i++) {
            let inter = new Interferencer(solution[2 * i], solution[2 * i + 1], inter_range);
            this.addInterfer(inter);
        }
    };

    // 整个群体的绘图方法
    this.draw = function () {
        // 绘制网格
        if (this.grid !== null) {
            this.grid.draw(this.canvas);
        }
        //  绘制目标
        for (let i = 0; i < this.target_list.length; i++) {
            this.target_list[i].draw(this.canvas);
        }
        //  绘制干扰物
        for (let i = 0; i < this.inter_list.length; i++) {
            this.inter_list[i].draw(this.canvas);
        }
        // 绘制无人机
        for (let uav of this.uav_list) {
            uav.draw(this.canvas, false,"dark", false);
        }
    }
}

export default Flock;